/*
 * rootGSL.h
 *
 *  Created on: 11-09-2012
 *      Author: mith
 */

#ifndef ROOTGSL_H_
#define ROOTGSL_H_

// BASIC LIBLARIES
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<math.h>
#include<time.h>
// GSL LIBLARIES
#include<gsl/gsl_vector.h> // GSL LIBRARY - remember use flag -lgsl -lgslcblas
#include<gsl/gsl_multiroots.h>
#include<gsl/gsl_errno.h> // to interpolation
#include<gsl/gsl_spline.h>
// EXTENDED LIBLARIES
#include<omp.h> // flaga -fopenmp
#include<cstring>
// My LIBRARIES
#include "mros-v42.h"

// DECLARATIONS
#define frand() ((double)rand()/(RAND_MAX+1.0))

// KLASY

class Parameters {
	public:
		virtual ~Parameters(){};

		virtual void print(FILE *file) const = 0;
		virtual void print_verboten(FILE *file) const = 0;
		virtual void print_label(FILE *file) const = 0;

		Parameters &operator=(const Parameters &rhs) { printf("[FAILURE: Operacja niezdefiniowana]"); exit(EXIT_FAILURE); }
};

class Variables {
	public:
		virtual ~Variables(){};

		virtual void print(FILE *file) const = 0;
		virtual void print_verboten(FILE *file) const = 0;
		virtual void print_label(FILE *file) const = 0;

		virtual double &operator[](int i) = 0;
		virtual const double &operator[](int i) const = 0;
		Variables &operator=(const Variables &rhs) { printf("[FAILURE: Operacja niezdefiniowana]"); exit(EXIT_FAILURE); }

		virtual int getNtabD() const = 0;
};

class Result {
	public:
		virtual ~Result(){};
		virtual void set(gsl_multiroot_fsolver *s) = 0;

		virtual void print(FILE *file) const = 0;
		virtual void print_verboten(FILE *file) const = 0;
		virtual void print_label(FILE *file) const = 0;
};

class RootGSL {
	private:
		Parameters *P;
		Result *R;
		int (*fun)(const gsl_vector*, void*, gsl_vector*);

	public:
		RootGSL(Parameters &P, int (*fun)(const gsl_vector*, void*, gsl_vector*), Result &R): P(&P), R(&R), fun(fun) {}
		~RootGSL(){}

		int Solve(Variables &InitV);

		void print_state (size_t iter, gsl_multiroot_fsolver * s, unsigned N_variables); // to debug
		void print(FILE *file=stdout) const;
		void print_verboten(FILE *file=stdout) const;
};

#endif /* ROOTGSL_H_ */
